# 数据库部分
# 写成一个类更加利于主程序导入和使用
import pymongo
from data import Todo


class TodoDB:
    def __init__(self):
        # 初始化本地数据库
        self.client = pymongo.MongoClient()
        # 使用todo数据库
        self.db = self.client['todo']
        # 使用这个数据库下的todo_list collection
        self.col = self.db['todo_list']

    def tid_init(self) -> int:
        # 设置tid作为MongoDB的自增键，用作唯一ID
        if len(list(self.col.find({'_id': 'tid'}, {'_id': 0}))) == 0:
            self.col.insert_one({
                '_id': 'tid',
                'sequence_value': 1,
            })
        return 0

    def tid_get_next(self):
        result = self.col.find_one_and_update({'_id': 'tid'},
                                              {'$inc': {'sequence_value': 1}})
        if result is None:
            return self.tid_init()
        return result['sequence_value']

    # 获取所有的List
    # 这里 -> list 的写法是标明函数返回值
    # 在写代码的时候如果返回值不正确，会给出警告，
    # 但是仍然能运行，而且返回return给出的类型
    # 这点和C/C++不同
    def get(self) -> list:
        # 从collection拿到所有的todo
        data = self.col.find({'tid': {'$gt': -1}}, {'_id': 0})
        # 转换数据格式到Todo
        data = list(map(lambda x: Todo.from_json_static(x), data))
        return data

    # 用Tid查找
    def get_by_tid(self, tid: int) -> Todo or None:
        data = list(self.col.find({'tid': tid}))
        if len(data) == 0:
            return None
        return Todo.from_json_static(data[0])

    # 插入一条Todo
    def insert(self, todo: Todo):
        # 如果tid为None说明还没初始化呢就给他一个新的值然后再插入
        if todo.tid is None:
            todo.tid = self.tid_get_next()
        # 如果找到同tid的就直接更新
        else:
            if self.get_by_tid(todo.tid) is not None:
                self.update(todo)
                return
        self.col.insert_one(todo.to_json())

    # 用tid更新一条todo
    # 返回更新是否成功...总之会成功
    def update(self, todo: Todo) -> bool:
        old = self.get_by_tid(todo.tid)
        if old is None:
            self.insert(todo)
            return True
        todo.tid = old.tid
        # print('update:', list(self.col.find({'tid': todo.tid})), 'set to', todo.to_json())
        self.col.update_one({'tid': todo.tid}, {'$set': todo.to_json()})
        return True


# 如果这个文件作为主程序运行
# 这里是测试程序的地方
if __name__ == '__main__':
    _db = TodoDB()
    # 测试插入
    _db.insert(Todo("新的TODO项目"))
    # 测试读取
    _todos = _db.get()
    print(_todos[0])
    # 测试更新
    _todo = _todos[0]
    _todo.finish()
    _todo.description = 'Yeah! All done!'
    _db.update(_todo)
    _todo = _db.get_by_tid(_todo.tid)
    print('modified:\n%s' % _todo)
